#include "ShareMemAO.h"
#include "Log.h"

using namespace ShareMemAPI;

bool ShareMemAO::Create(SM_KEY key, SM_SIZE size) {
    __ENTER_FUNCTION

    // 判断当前模式
    if (m_CmdArg == CMD_MODE_CLEARALL)
        return false;

    // 创建指定key和size的共享内存区
    m_hold = ShareMemAPI::CreateShareMem(key, size);
    if (m_hold == INVALID_SM_HANDLE) {
        Log::SaveLog(SHMEM_LOG_PATH, "Create ShareMem Error SM_KET = %d", key);
        return false;
    }
    
    // 获得共享内存区的映射指针，起始点
    m_pHeader = ShareMemAPI::MapShareMem(m_hold);

    if (m_pHeader) {
        // 设置数据开始指针地址，起始点
        m_pDataPtr = (char*) m_pHeader + sizeof (SMHead);
        // 设置Head信息，key 和 size信息
        ((SMHead*) m_pHeader)->m_Key = key;
        ((SMHead*) m_pHeader)->m_Size = size;
        // 数据块大小
        m_Size = size;
       
        Log::SaveLog(SHMEM_LOG_PATH, "Create ShareMem Ok SM_KET = %d", key);
        return true;
    } else {
        Log::SaveLog(SHMEM_LOG_PATH, "Map ShareMem Error SM_KET = %d", key);
        return false;
    }



    __LEAVE_FUNCTION
    return false;
}

void ShareMemAO::Destory() {
    __ENTER_FUNCTION
    if (m_pHeader) {
        // 关闭共享内存映射
        ShareMemAPI::UnMapShareMem(m_pHeader);
        m_pHeader = 0;
    }
    if (m_hold) {
        // 关闭共享内存区
        ShareMemAPI::CloseShareMem(m_hold);
        m_hold = 0;
    }
    m_Size = 0;
    __LEAVE_FUNCTION
}

bool ShareMemAO::Attach(SM_KEY key, SM_SIZE size) {
    __ENTER_FUNCTION
    // 根据key和size打开共享内存区
    m_hold = ShareMemAPI::OpenShareMem(key, size);
    // 判断命令模式
    if (m_CmdArg == CMD_MODE_CLEARALL) {
        Destory(); // 销毁共享内存区
        printf("Close ShareMemory key = %d \r\n", key);
        return false;
    }
    // 打开失败！
    if (m_hold == INVALID_SM_HANDLE) {
        Log::SaveLog(SHMEM_LOG_PATH, "Attach ShareMem Error SM_KET = %d", key);
        return false;
    }
    // 映射共享内存区，获得内存块首地址
    m_pHeader = ShareMemAPI::MapShareMem(m_hold);
    if (m_pHeader) {
        // 设置数据内容开始内存块首地址
        m_pDataPtr = (char*) m_pHeader + sizeof (SMHead);
        // 判断key和size是否与之前创建时一致
        Assert(((SMHead*) m_pHeader)->m_Key == key);
        Assert(((SMHead*) m_pHeader)->m_Size == size);
        m_Size = size;
        Log::SaveLog(SHMEM_LOG_PATH, "Attach ShareMem OK SM_KET = %d", key);
        return true;
    } else {
        Log::SaveLog(SHMEM_LOG_PATH, "Map ShareMem Error SM_KET = %d", key);
        return false;
    }
    __LEAVE_FUNCTION
    return false;

}

bool ShareMemAO::DumpToFile(char* FilePath) {
    __ENTER_FUNCTION
    // 将内存数据写入文本操作
    Assert(FilePath);
    FILE* f = fopen(FilePath, "wb");
    if (!f)
        return false;
    fwrite(m_pHeader, 1, m_Size, f);
    fclose(f);
    return true;
    __LEAVE_FUNCTION
    return false;
}

bool ShareMemAO::MergeFromFile(char* FilePath) {
    __ENTER_FUNCTION
    // 将文本数据加载到内存操作
    Assert(FilePath);
    FILE* f = fopen(FilePath, "rb");
    if (!f)
        return false;
    fseek(f, 0L, SEEK_END);
    int FileLength = ftell(f);
    fseek(f, 0L, SEEK_SET);
    fread(m_pHeader, FileLength, 1, f);
    fclose(f);
    return true;
    __LEAVE_FUNCTION
    return false;
}

void ShareMemAO::SetHeadVer(uint ver) {
    __ENTER_FUNCTION
            // 版本信息
            ((SMHead*) m_pHeader)->m_HeadVer = ver;
    __LEAVE_FUNCTION
}

uint ShareMemAO::GetHeadVer() {
    __ENTER_FUNCTION
    // 获得版本信息
    uint ver = ((SMHead*) m_pHeader)->m_HeadVer;
    return ver;
    __LEAVE_FUNCTION
    return 0;
}